package com.nulldev.util.web.nTubeExtensions.gvc_spoofer;

import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;

/**
 * TODO: <br>
 * - Figure out the types for everything <br>
 * - Wrap around JavaScript's DataView (i hate webshitters) <br>
 * - Finish the implementation
 */
final class GVCPostDataManipulator {

	private static void __typed_array_set(final int[] arr, final int[] data, final int idx) {
		for (int i = 0; i < data.length; i++) {
			arr[idx + i] = data[i];
		}
	}

	private static int[] __subarray(final int[] arr, final int start) {
		return __subarray(arr, start, arr.length);
	}

	private static int[] __subarray(final int[] arr, final int start, final int end) {
		return Arrays.copyOfRange(arr, start, end);
	}

	private static void __setUint8(final int[] a, final int pos, final int val) {
		a[pos] = val;
	}

	private static double __log2(final int n) {
		return (Math.log(n) / Math.log(2));
	}

	class __TEMPORARY_STUB {

		int push() {
			return -1;
		}

		int pop() {
			return -1;
		}

	}

	class A {
		int pos;
		int[] j;

		/* unknowns */
		__TEMPORARY_STUB B;
		Object C;
	}

	private static int[] UHa(final int a, final Object b, final int[] c) {
		final int[] _a = new int[a];
		if (c != null)
			__typed_array_set(_a, c, 0);
		return _a;
	}

	private static void KO(final A a, double b) {
		b = a.pos + b;
		if (!(a.j.length >= b)) {
			int c = 2 * a.j.length;
			for (; c < b;)
				c *= 2;
			a.j = UHa(c, a.C, __subarray(a.j, 0, a.pos));
//			a.view = new DataView(a.j.buffer, a.j.byteOffset, a.j.byteLength);
		}
	}

	private static void LO(final A a, int b) {
		if (268435455 < b) {
			KO(a, 4);
			for (int c = b & 1073741823, d = 0; 4 > d; d++) {
				__setUint8(a.j, a.pos, c & 127 | 128);
				c >>= 7;
				a.pos += 1;
			}
			b = (int) Math.floor(b / 268435456);
		}
		for (KO(a, 4); 127 < b;) {
			__setUint8(a.j, a.pos, b & 127 | 128);
			b >>= 7;
			a.pos += 1;
		}
		__setUint8(a.j, a.pos, b);
		a.pos += 1;
	}

	private static void OO(final A a, int b, final int[] c) {
		if (c.length == 0)
			return;
		LO(a, 8 * b + 2);
		b = c.length;
		LO(a, b);
		KO(a, b);
		__typed_array_set(a.j, c, a.pos);
		a.pos += b;
	}

	private static void XHa(final A a) {
		for (int b = a.B.pop(), c = a.B.pop(), d = a.pos - c - b;; b--) {
			int e = 0; /* FIXME: b ? 128 : 0; */
			__setUint8(a.j, c++, d & 127 | e);
			d >>= 7;
		}
	}

	private static void OO(A a, int b, Object c) {
		throw new UnsupportedOperationException("TODO");
	}

	private static void QO(final A a, int b, final Object c, final Function<Object, Object> d, final int e) {
		throw new UnsupportedOperationException("TODO");
	}

	private static void QO(final A a, int b, final int[] c, final Function<Object, Object> d, final int e) {
		throw new UnsupportedOperationException("TODO");
	}

	private static void MO(final A a, final int b, final Object c) {
		LO(a, 8 * b);
		LO(a, (int) c); /* FIXME */
	}

	private static void PO(final A a, int b, final Object c) {
		throw new UnsupportedOperationException("TODO");
	}

	private static void PO(final A a, int b, final Object[] c) {
		WHa(a, b, Math.ceil(__log2(4 * c.length + 2) / 7));
		KO(a, 1.2 * c.length);
		b = yO(c, __subarray(a.j, a.pos));
		if (a.pos + b > a.j.length) {
			KO(a, b);
			b = yO(c, __subarray(a.j, a.pos));
		}
		a.pos += b;
		XHa(a);
	}

	private static void WHa(A a, int b, double c) {
		throw new UnsupportedOperationException("TODO");
	}

	private static int yO(Object a, int[] b) {
		throw new UnsupportedOperationException("TODO");
	}

	private static void AUa(final A a, final Map<String, Object> b) {
		PO(a, 12, b.get("deviceMake"));
		PO(a, 13, b.get("deviceModel"));
		MO(a, 16, b.get("clientName"));
		PO(a, 17, b.get("clientVersion"));
		PO(a, 18, b.get("osName"));
		PO(a, 19, b.get("osVersion"));
	}

	private static Function<Object, Object> AUa = null;

	public static void vUa(final A a, final Map<String, Object> b) {
		QO(a, 1, b.get("clientInfo"), AUa, 3);
		OO(a, 2, b.get("bR"));
		OO(a, 3, b.get("playbackCookie"));
		OO(a, 4, b.get("Io"));
	}

	public static void main(String[] args) {
	}

}
